// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * CodeBase.h
 *
 *  Created on: Nov 24, 2009
 *      Author: dhovemey
 */

#ifndef CODEBASE_H_
#define CODEBASE_H_

#include <map>
#include <vector>
#include <string>

class Class;

/**
 * A CodeBase is a collection of Classes.
 * The Classes may be loaded from a directories specified by
 * a class path.
 */
class CodeBase {
public:
	typedef std::map<std::wstring, Class *> ClassMap;
	typedef std::vector<std::string> ClassPath;

private:
	ClassMap m_clsMap;
	std::string m_thudHomeDir;
	ClassPath m_classPath;

	CodeBase(const CodeBase &);
	CodeBase& operator=(const CodeBase &);

public:
	/**
	 * Constructor.
	 */
	CodeBase();

	/**
	 * Destructor.
	 */
	~CodeBase();

	/**
	 * Set the Thud home directory.
	 * We will attempt to infer it from the path of the executable:
	 * if that doesn't work, we'll try the $THUD_HOME environment variable.
	 * If neither of those work, throw an exception.
	 *
	 * @param progName path of executable
	 */
	void setThudHomeDirectory(const std::string &progName);

	/**
	 * Create a new class in this CodeBase.
	 * @param clsName name of class to create
	 * @return the new Class object
	 */
	Class *createClass(const std::wstring &clsName);

	/**
	 * Get Class object for named class from this CodeBase,
	 * without searching the class path.
	 * Throws exception if class is not currently present in
	 * the CodeBase.
	 *
	 * @param clsName name of a class
	 * @return the Class object for the named class
	 */
	Class *getClass(const std::wstring &clsName);

	/**
	 * Get the "Main$" class from this CodeBase.
	 * Throws exception if "Main$" class is not currently present in
	 * the CodeBase.
	 * @return the Class object for the "Main$" class
	 */
	Class *getMainClass() { return getClass(L"Main$"); }

	/**
	 * Set class path: directories to search for referenced classes.
	 *
	 * @param classPathStr a string representation of the class path
	 */
	void setClassPath(const std::string &classPathStr);

	/**
	 * Load a class.
	 * Class path will be searched if the class is not
	 * currently present in the CodeBase.
	 * Throws exception if class cannot be located.
	 *
	 * @param clsName name of class to load
	 * @return the Class object for the named class
	 */
	Class *loadClass(const std::wstring &clsName);

	/**
	 * Get the map of class names to currently-loaded Class objects.
	 */
	const ClassMap &getClassMap() const { return m_clsMap; }

private:
	Class *attemptToLoadClass(const std::wstring &clsName, const std::string &dirPath, const std::string &clsNamePath);
};

#endif /* CODEBASE_H_ */
